using System;
using System.IO;
using Dida.Dbg;

namespace Dida
{
	[Dxml.DidaObject]
	public class StaticCollisionMesh
	{
		CollisionTree collisionTree;
		DebugMesh debugMesh = null;
		
		[Dxml.AutoXmlConstructor]
		public StaticCollisionMesh(Stream src,
			[Dxml.ParamDefault(16)] int maxTrisPerNode,
			[Dxml.ParamDefault(.4f)] float maxOverlap)
		{
			MeshLoader meshLoader = new MeshLoader(src);

			CollisionTreeSettings settings = new CollisionTreeSettings();
			settings.MaxTrisPerNode = maxTrisPerNode;
			settings.MaxOverlap = maxOverlap;
			collisionTree = new CollisionTree(meshLoader, settings);
		}

		public CollisionTree CollisionTree
		{
			get { return collisionTree; }
		}

		public void DrawDebug(IDebugDrawTarget target)
		{
			if (debugMesh == null)
			{
				debugMesh = DebugDraw.CreateDebugMesh();
				debugMesh.Begin();
				collisionTree.DrawToDebugMesh(debugMesh);
				debugMesh.End();
			}

			target.DrawDebugMesh(debugMesh);
		}
	}

	[Dxml.DidaObject]
	public class DynamicCollisionMesh : Actor, IDynamicCollisionObject
	{
		CollisionTree collisionTree;
		DebugMesh debugMesh;

		AniSocket<SimpleTransform> transform;

		[Dxml.AutoXmlConstructor]
		public DynamicCollisionMesh(AniSocket<SimpleTransform> transform,Stream src,
			[Dxml.ParamDefault(16)] int maxTrisPerNode,
			[Dxml.ParamDefault(.4f)] float maxOverlap)
		{
			this.transform = transform;

			MeshLoader meshLoader = new MeshLoader(src);

			CollisionTreeSettings settings = new CollisionTreeSettings();
			settings.MaxTrisPerNode = maxTrisPerNode;
			settings.MaxOverlap = maxOverlap;
			collisionTree = new CollisionTree(meshLoader, settings);
		}

		public CollisionTree CollisionTree
		{
			get { return collisionTree; }
		}

		public float BoundingSphereRadius
		{
			get { return collisionTree.PivottedBoundingSphere.radius; }
		}

		public override Box BoundingBox
		{
			get
			{
				OrientedBox bbox = new OrientedBox(collisionTree.BoundingBox,transform.Value);
				return bbox.AxisAlignedBoundingBox;
			}
		}

		protected override SimpleTransform GetTransform()
		{
 			return transform.Value;
		}

		SimpleTransform IDynamicCollisionObject.Transform
		{
			get { return transform.Value; }
		}

		public override void DrawDebug(IDebugDrawTarget target)
		{
			if (debugMesh == null)
			{
				debugMesh = DebugDraw.CreateDebugMesh();
				debugMesh.Begin();
				collisionTree.DrawToDebugMesh(debugMesh);
				debugMesh.End();
			}

			// NOTE: The push/pop semantics may give you a different impression, 
			// but the Transformation is the full transformation, from object to world
			// space, without parenting. The DrawDebug calls are made sequentially, 
			// not recursively.
			target.PushWorldMatrix(Transform.ToMatrix());
			target.DrawDebugMesh(debugMesh);
			target.PopWorldMatrix();

			base.DrawDebug(target);
		}
	}
}